#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>


#define NUM 1024
#define SIZE 32
#define SEP " "

//保存完整的命令行字符串
char cmd_line[NUM];
//保存打散后的命令行字符串
char *g_argv[SIZE];

//shell运行原理：通过让子进程执行命令，父进程等待和解析命令
int main()
{
    //0.命令行解释器，是一个常驻内存的进程，不退出
    while(1)
    {
        //1.打印出提示信息:[ljx@localhost myshell]#
        printf("[ljx@localhost myshell]#");
        fflush(stdout);
        memset(cmd_line, '\0', sizeof(cmd_line));
        
        //2.获取用户输入的键盘输入，输入的是各种指令和选项
        if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
        {
            continue;
        }
        cmd_line[strlen(cmd_line) - 1] = '\0';
        //printf("%s\n", cmd_line);
        
        //3.命令行字符串解析
        g_argv[0] = strtok(cmd_line, SEP);//第一次调用要传入原始字符串 
        int i = 1;
        if(strcmp(g_argv[0], "ls") == 0)
        {
            g_argv[i++] = "--color=auto";
        }
        if(strcmp(g_argv[0], "ll") == 0)
        {
            g_argv[0] = "ls";
            g_argv[i++] = "--color=auto";
            g_argv[i++] = "-l";

        }
        while(g_argv[i++] = strtok(NULL, SEP));//第二次，如果还要解析原始字符串，传入NULL
        
        //4.TODO 内置命令/内建命令，让父进程(shell)自己执行的命令
        //内建命令本质其实就是shell中的一个函数调用
        if(strcmp(g_argv[0], "cd") == 0)
        {
            if(g_argv[1] != NULL)
            {
                chdir(g_argv[1]);
            }
            continue;
        }
        
        //5.创建子进程
        pid_t id = fork();
        if(id == 0)
        {
            printf("子进程执行下面的命令\n");
            execvp(g_argv[0], g_argv);
            exit(1);
        }
        int status = 0;
        pid_t ret = waitpid(id, &status, 0);
        if(ret > 0)
        {
            printf("退出码:%d\n", WEXITSTATUS(status));
        }






    }
    




    return 0;
}
